import 抽象语法树节点.*;

import java.util.ArrayList;

public class Cymbol访问器 extends CymbolBaseVisitor<抽象语法树> {
    @Override
    public 抽象语法树 visitCompilationUnit(CymbolParser.CompilationUnitContext ctx) {
        var 结果 = new 编译单元();
        结果.子节点 = new ArrayList<>();

        for (var 节点 : ctx.children) {
            结果.子节点.add(visit(节点));
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitClassDefinition(CymbolParser.ClassDefinitionContext ctx) {
        var 结果 = new 类定义();

        结果.名称 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();

        if (ctx.superClass() != null) {
            结果.父类名 = ctx.superClass().ID().getText();
        }

        结果.成员 = new ArrayList<>();
        for (var 成员 : ctx.classMember()) {
            var 成员节点 = visit(成员);
            if (成员节点 == null) continue;
            结果.成员.add(成员节点);
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitClassFieldDeclaration(CymbolParser.ClassFieldDeclarationContext ctx) {
        var 结果 = new 字段定义();

        结果.名称 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();
        结果.类型 = ctx.type().getText();

        if (ctx.expression() != null) {
            结果.初值 = visit(ctx.expression());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitClassMethodDeclaration(CymbolParser.ClassMethodDeclarationContext ctx) {
        var 结果 = new 方法定义();

        结果.名称 = ctx.methodDeclaration().ID().getText();
        结果.idToken = ctx.methodDeclaration().ID().getSymbol();
        结果.返回值类型 = ctx.methodDeclaration().type().getText();

        if (ctx.methodDeclaration().formalParameters() != null) {
            结果.参数列表 = visit(ctx.methodDeclaration().formalParameters());
        }

        结果.代码块 = visit(ctx.methodDeclaration().block());
        return 结果;
    }


    @Override
    public 抽象语法树 visitFormalParameters(CymbolParser.FormalParametersContext ctx) {
        var 结果 = new 参数列表();
        结果.参数 = new ArrayList<>();

        for (var i = 0; i < ctx.type().size(); i++) {
            var 参数 = new 参数定义();
            参数.名称 = ctx.ID(i).getText();
            参数.idToken = ctx.ID(i).getSymbol();
            参数.类型 = ctx.type(i).getText();
            结果.参数.add(参数);
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitBlock(CymbolParser.BlockContext ctx) {
        var 结果 = new 代码块();
        结果.子节点 = new ArrayList<>();

        if (ctx.children != null) {
            for (var 节点 : ctx.children) {
                var 子节点 = visit(节点);
                if (子节点 == null) continue;
                结果.子节点.add(子节点);
            }
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitVarDeclaration(CymbolParser.VarDeclarationContext ctx) {
        var 结果 = new 变量定义();

        结果.名称 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();
        结果.类型 = ctx.type().getText();

        if (ctx.expression() != null) {
            结果.初值 = visit(ctx.expression());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitBlockStatement(CymbolParser.BlockStatementContext ctx) {
        return visit(ctx.block());
    }

    @Override
    public 抽象语法树 visitVarDeclarationStatement(CymbolParser.VarDeclarationStatementContext ctx) {
        return visit(ctx.varDeclaration());
    }

    @Override
    public 抽象语法树 visitReturnStatement(CymbolParser.ReturnStatementContext ctx) {
        var 结果 = new 返回语句();

        if (ctx.expression() != null) {
            结果.表达式 = visit(ctx.expression());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitCallStatement(CymbolParser.CallStatementContext ctx) {
        return visit(ctx.postfixExpression());
    }

    @Override
    public 抽象语法树 visitAssignmentExpression(CymbolParser.AssignmentExpressionContext ctx) {
        var 结果 = new 赋值语句();
        结果.左值 = visit(ctx.postfixExpression());
        结果.右值 = visit(ctx.expression());
        return 结果;
    }

    @Override
    public 抽象语法树 visitAddExpression(CymbolParser.AddExpressionContext ctx) {
        if (ctx.postfixExpression().size() == 1) {
            return visit(ctx.postfixExpression().get(0));
        }
        
        var 结果 = new 加法表达式();
        结果.左操作数 = visit(ctx.postfixExpression(0));

        var 当前表达式 = 结果;
        for (var i = 1; i < ctx.postfixExpression().size() - 1; i++) {
            var 右值 = new 加法表达式();
            右值.左操作数 = visit(ctx.postfixExpression(i));
            当前表达式.右操作数 = 右值;
            当前表达式 = 右值;
        }

        当前表达式.右操作数 = visit(ctx.postfixExpression(ctx.postfixExpression().size() - 1));
        return 结果;
    }

    @Override
    public 抽象语法树 visitPostfixExpression(CymbolParser.PostfixExpressionContext ctx) {
        var 结果 = visit(ctx.primary());
        if (ctx.option() == null) {
            return 结果;
        }

        var 当前表达式 = 结果;

        for (var i = 0; i < ctx.option().size(); i++) {
            var 表达式 = visit(ctx.option().get(i));
            if (表达式 instanceof 方法调用 方法调用表达式) {
                方法调用表达式.对象 = 当前表达式;
            } else if (表达式 instanceof 成员访问 成员访问表达式) {
                成员访问表达式.对象 = 当前表达式;
            } else if (表达式 instanceof 函数调用 函数调用表达式) {
                函数调用表达式.对象 = 当前表达式;
            }

            当前表达式 = 表达式;
        }

        return 当前表达式;
    }

    @Override
    public 抽象语法树 visitMethodCall(CymbolParser.MethodCallContext ctx) {
        var 结果 = new 方法调用();
        结果.方法名 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();
        if (ctx.expressionList() != null) {
            结果.参数列表 = visit(ctx.expressionList());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitMemberAccess(CymbolParser.MemberAccessContext ctx) {
        var 结果 = new 成员访问();
        结果.成员名 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();
        return 结果;
    }

    @Override
    public 抽象语法树 visitFunctionCall(CymbolParser.FunctionCallContext ctx) {
        var 结果 = new 函数调用();
        if (ctx.expressionList() != null) {
            结果.参数列表 = visit(ctx.expressionList());
        }

        return 结果;
    }

    @Override
    public 抽象语法树 visitMethodDeclaration(CymbolParser.MethodDeclarationContext ctx) {
        var 结果 = new 方法定义();
        结果.名称 = ctx.ID().getText();
        结果.idToken = ctx.ID().getSymbol();
        结果.返回值类型 = ctx.type().getText();

        if (ctx.formalParameters() != null) {
            结果.参数列表 = visit(ctx.formalParameters());
        }

        结果.代码块 = visit(ctx.block());
        return 结果;
    }

    @Override
    public 抽象语法树 visitPrimary(CymbolParser.PrimaryContext ctx) {
        if (ctx.THIS() != null) {
            var this访问器 = new This访问器();
            this访问器.idToken = ctx.THIS().getSymbol();
            return this访问器;
        }
        
        if (ctx.SUPER() != null) {
            var super访问器 = new Super访问器();
            super访问器.idToken = ctx.SUPER().getSymbol();
            return super访问器;
        }

        if (ctx.ID() != null) {
            var 标识符 =  new 标识符(ctx.ID().getText());
            标识符.idToken = ctx.ID().getSymbol();
            return 标识符;
        }
        
        if (ctx.INT() != null) {
            return new 整型字面量(Integer.parseInt(ctx.INT().getText()));
        }
        
        return visit(ctx.expression());
    }
}
